program constraint_array;

class DynamicIntArray;
    rand int data [];
    constraint dync {
        // 约束数组的大小
        data.size() inside { [1:10] };
        // 约束数组的值
        foreach (data[i]) data[i] inside { [1:10] };
        // 约束数组的和
        data.sum() < 60;
    }
endclass

class Packet;
    logic [7:0] data;
    logic [7:0] addr;
    function new(logic [7:0] addr, logic [7:0] data);
        this.addr = addr;
        this.data = data;
    endfunction
endclass

class DynamicPacketArray;
    rand Packet data [];
    constraint dync {
        // 约束数组的大小
        data.size() inside { [1:10] };
    }
/*
    // 错误示例: 
    function void pre_randomize();
        // 约束数组的值
        foreach (data[i]) begin
            data[i] = new($urandom_range(0, 255), $urandom_range(0, 255));
        end
    endfunction

    输出内容:
        Randomized DynamicPacketArray: '{null,null,null,null,null,null,null,null}
        Randomized DynamicPacketArray: '{'{data:246,addr:212},'{data:193,addr:197},'{data:168,addr:67},'{data:23,addr:205},'{data:146,addr:159}}
        Randomized DynamicPacketArray: '{'{data:209,addr:55}}
        Randomized DynamicPacketArray: '{'{data:108,addr:187},'{data:65,addr:171},'{data:204,addr:115},'{data:46,addr:62},'{data:234,addr:56},'{data:171,addr:112},'{data:174,addr:182},null}
        Randomized DynamicPacketArray: '{'{data:238,addr:217},'{data:73,addr:152},'{data:78,addr:153},'{data:114,addr:248}}
        Randomized DynamicPacketArray: '{'{data:4,addr:68},'{data:35,addr:241}}
        Randomized DynamicPacketArray: '{'{data:48,addr:61},'{data:245,addr:32},null,null,null}
        Randomized DynamicPacketArray: '{'{data:95,addr:105}}
        Randomized DynamicPacketArray: '{'{data:255,addr:158},null,null,null,null,null,null}

    为什么会有 null?
    第一次调用 randomize(), 初始时 data[] 是空的; pre_randomize() 执行, 但由于 data[] 没有元素, foreach 循环不做任何事; 
    randomize() 将 data.size() 设置为某个值（比如 8）, 此时 data[] 变成 {null, null, null, null, null, null, null, null}.
    第二次调用 randomize(), pre_randomize() 看到 data[] 有 8 个元素（全是 null）, 故为每个元素分配一个新的 Packet 对象. 
    randomize() 再次调整大小, 比如变成 5. 此时 data[] 变成 '{'{data:246,addr:212},'{data:193,addr:197},'{data:168,addr:67},'{data:23,addr:205},'{data:146,addr:159}}. 
*/
    function void post_randomize();
        foreach (data[i]) begin
            if (data[i] == null) begin
                // 如果数组元素为null, 则创建一个新的 Packet 对象
                data[i] = new(0, 0);
            end
            data[i] = new($urandom_range(0, 255), $urandom_range(0, 255));
        end
    endfunction
endclass

initial begin
    begin
        DynamicIntArray arr = new();
        $display("Testing DynamicIntArray:");
        for(int i = 0; i < 10; i++) begin
            // randomize() 的行为: randomize() 会根据约束 dync（data.size() inside { [1:10] };）随机选择一个数组大小（1到10之间）, 并调整 data[] 的大小:
            //      如果新的size比之前的大, 数组会扩展, 新添加的元素默认是null; 如果新的size比之前的小, 数组会缩减, 多余的元素被丢弃.
            if (arr.randomize()) begin
                $display("Randomized DynamicIntArray: %p", arr.data);
            end else begin
                $display("Randomization failed");
            end
        end
    end

    begin
        DynamicPacketArray arr = new();
        $display("Testing DynamicPacketArray:");
        for(int i = 0; i < 10; i++) begin
            if (arr.randomize()) begin
                $display("Randomized DynamicPacketArray: %p", arr.data);
            end else begin
                $display("Randomization failed");
            end
        end
    end
end

endprogram
